﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AzukiMap.MapSource;
using System.Xml.Linq;
using AzukiMap;
using AzukiMap.MapSource.Vector;

namespace AzukiMapUI
{
    public partial class PostGISTableProperties : UserControl, IMapSourceProperties
    {
        const string GEOM_COLUMN_REQ_TARGET = "getGeometryColumns.php";
        const string REQ_PARAM_PG_DB = "db";

        string _serverPath;
        string _dbName;
        XDocument _geomColumnsXml;

        List<PostGisSource> _pgSources;
        //MapSourceType _mapSourceType;
        VectorSourceTypes _vectorType;

        public MapSource MapDataSource
        {
            get { return GetSelectedDataSource(); }
        }

        public PostGisSource PGSource
        {
            get { return GetSelectedDataSource(); }
        }

        public PostGISTableProperties()
        {
            InitializeComponent();
            _geomColumnsXml = new XDocument();
            //_mapSourceType = new MapSourceType(MapSourceTypes.Point);
            _vectorType = VectorSourceTypes.Point;
        }

        PostGisSource GetSelectedDataSource()
        {
            int selectedIndex = CbGeomColumn.SelectedIndex;
            if (selectedIndex < 0)
            {
                return null;
            }
            return _pgSources[selectedIndex];
        }

        void GetGeomColumns()
        {
            string uriStr = string.Format("{0}/{1}?{2}={3}", 
                _serverPath, GEOM_COLUMN_REQ_TARGET, REQ_PARAM_PG_DB, _dbName);
            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
            webClient.DownloadStringAsync(new Uri(uriStr));
        }

        void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                string res = e.Result;
                SetGeomColumnCombo(res);
                FormInputControl.ShowElement(GrGeomSelection);
            }
            else
            {
                FormInputControl.HideElement(GrGeomSelection);
                FormInputControl.ShowElement(IconErrorConnection);
                FormInputControl.ShowElement(TbErrorMessage);
                TbErrorMessage.Text = e.Error.Message;
            }
        }

        void SetGeomColumnCombo(string resXml)
        {
            _geomColumnsXml = XDocument.Parse(resXml);
            IEnumerable<PostGisSource> sources = from elem in _geomColumnsXml.Descendants("geometryColumn")
                         select new PostGisSource
                         { 
                             DbName = (string)elem.Attribute("db"),
                             TableCatalog = (string)elem.Element("f_table_catalog"),
                             TableSchema = (string)elem.Element("f_table_schema"),
                             TableName = (string)elem.Element("f_table_name"),
                             GeometryColumn = (string)elem.Element("f_geometry_column"),
                             //= (int)elem.Element("coord_dimension"),
                             Srid = (int)elem.Element("srid"),
                             //Type = _mapSourceType.SetTypeByString((string)elem.Element("type")),
                             VectorType = (VectorSourceTypes)Enum.Parse(typeof(VectorSourceTypes), elem.Element("type").Value, true),
                             Name = (string)elem.Attribute("db") + "_" +
                                    (string)elem.Element("f_table_schema") + "_" +
                                    (string)elem.Element("f_table_name"),
                             GetColumnDataUri = _serverPath + AzukiMapSettings.GET_POSTGISDATA
                         };

            CbGeomColumn.Items.Clear();

            _pgSources = new List<PostGisSource>(sources);
            foreach (PostGisSource pgSource in _pgSources)
            {
                TextBlock tb = new TextBlock();
                tb.Text = pgSource.TableName + "." + pgSource.GeometryColumn;
                CbGeomColumn.Items.Add(tb);
            }
        }

        #region handlers

        void BtnConnect_Click(object sender, RoutedEventArgs e)
        {
            if (CheckServerPath() && CheckDbName())
            {
                _serverPath = TbServerPath.Text;
                _dbName = TbDbName.Text;
                GetGeomColumns();
            }
        }

        void TbServerPath_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckServerPath();
            SetConnectButtonCondition();
        }

        void TbDbName_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckDbName();
            SetConnectButtonCondition();
        }

        void SetConnectButtonCondition()
        {
            if (CheckServerPath() && CheckDbName())
            {
                BtnConnect.IsEnabled = true;
            }
            else
            {
                BtnConnect.IsEnabled = false;
            }
        }

        #endregion

        #region checkers

        public bool CheckAllFormData()
        {
            bool isOk1 = CheckServerPath();
            bool isOk2 = CheckDbName();
            bool isOk3 = CheckTableName();
            return (isOk1 && isOk2);
        }

        bool CheckServerPath()
        {
            string inputStr = TbServerPath.Text;
            return FormInputControl.CheckUri(inputStr, IconErrorServerPath);
        }

        bool CheckDbName()
        {
            string inputStr = TbDbName.Text;
            return FormInputControl.HasData(inputStr, IconErrorDbName);
        }

        bool CheckTableName()
        {
            return (CbGeomColumn.SelectedIndex != -1);
        }

        #endregion

        private void CbGeomColumn_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            int selectedIndex = ((ComboBox)sender).SelectedIndex;
            if (selectedIndex < 0)
            {
                return;
            }
            SetSourceDescriptions(_pgSources[selectedIndex]);
        }

        void SetSourceDescriptions(PostGisSource pgSource)
        {
            TbkSchema.Text = pgSource.TableSchema;
            TbkCatalog.Text = pgSource.TableCatalog;
            TbkGeomType.Text = pgSource.Type.ToString();
            TbkSrid.Text = pgSource.Srid.ToString();
        }
    }
}
